// Copyright Epic Games, Inc. All Rights Reserved.

#include "LyraPlayerStart.h"

#include "Engine/World.h"
#include "GameFramework/GameModeBase.h"
#include "TimerManager.h"

#include UE_INLINE_GENERATED_CPP_BY_NAME(LyraPlayerStart) // 包含由UE生成的代码

/**
 * 构造函数。
 */
ALyraPlayerStart::ALyraPlayerStart(const FObjectInitializer& ObjectInitializer)
	: Super(ObjectInitializer)
{
}

/**
 * 获取位置占用状态。
 */
ELyraPlayerStartLocationOccupancy ALyraPlayerStart::GetLocationOccupancy(AController* const ControllerPawnToFit) const
{
	UWorld* const World = GetWorld(); // 获取世界
	if (HasAuthority() && World) // 如果有权限且世界存在
	{
		if (AGameModeBase* AuthGameMode = World->GetAuthGameMode()) // 获取认证游戏模式
		{
			TSubclassOf<APawn> PawnClass = AuthGameMode->GetDefaultPawnClassForController(ControllerPawnToFit); // 获取默认角色类
			const APawn* const PawnToFit = PawnClass ? GetDefault<APawn>(PawnClass) : nullptr; // 获取要适配的角色

			FVector ActorLocation = GetActorLocation(); // 获取角色位置
			const FRotator ActorRotation = GetActorRotation(); // 获取角色旋转

			if (!World->EncroachingBlockingGeometry(PawnToFit, ActorLocation, ActorRotation, nullptr)) // 如果没有侵入阻挡几何体
			{
				return ELyraPlayerStartLocationOccupancy::Empty; // 返回空
			}
			else if (World->FindTeleportSpot(PawnToFit, ActorLocation, ActorRotation)) // 如果找到传送点
			{
				return ELyraPlayerStartLocationOccupancy::Partial; // 返回部分占用
			}
		}
	}

	return ELyraPlayerStartLocationOccupancy::Full; // 返回满
}

/**
 * 检查是否被声明。
 */
bool ALyraPlayerStart::IsClaimed() const
{
	return ClaimingController != nullptr; // 返回是否被声明
}

/**
 * 尝试声明出生点。
 */
bool ALyraPlayerStart::TryClaim(AController* OccupyingController)
{
	if (OccupyingController != nullptr && !IsClaimed()) // 如果控制器存在且未被声明
	{
		ClaimingController = OccupyingController; // 设置声明控制器
		if (UWorld* World = GetWorld()) // 获取世界
		{
			World->GetTimerManager().SetTimer(ExpirationTimerHandle, FTimerDelegate::CreateUObject(this, &ALyraPlayerStart::CheckUnclaimed), ExpirationCheckInterval, true); // 设置过期检查计时器
		}
		return true; // 返回成功
	}
	return false; // 返回失败
}

/**
 * 检查未声明。
 */
void ALyraPlayerStart::CheckUnclaimed()
{
	if (ClaimingController != nullptr && ClaimingController->GetPawn() != nullptr && GetLocationOccupancy(ClaimingController) == ELyraPlayerStartLocationOccupancy::Empty) // 如果声明控制器存在且有角色且位置为空
	{
		ClaimingController = nullptr; // 清除声明控制器
		if (UWorld* World = GetWorld()) // 获取世界
		{
			World->GetTimerManager().ClearTimer(ExpirationTimerHandle); // 清除计时器
		}
	}
}